package com.ifood.framework.aspectj;

import com.alibaba.fastjson2.JSONObject;
import com.ifood.common.core.domain.model.LoginUser;
import com.ifood.common.utils.SecurityUtils;
import com.ifood.common.utils.ip.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author donghc
 * @ClassName ControllerLogAspect
 * @description: TODO
 * @date 2024年01月08日
 * @version: 1.0
 */
@Slf4j
@Aspect
@Component
public class ControllerLogAspect {
    /**
     * 定义切入点（需要拦截的切面）
     */
    @Pointcut("execution(public * com.ifood.*.controller..*.*(..))")
    public void controllerMethod() {
    }

    /**
     * 进入方法请求执行前
     *
     * @param joinPoint
     */
    @Before("controllerMethod()")
    public void LogRequestInfo(JoinPoint joinPoint) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return;
        }
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        Signature signature = joinPoint.getSignature();

        //排除方法
        if (signature.getName().contains("export")) {
            return;
        }
        //健康检测跳过
        if (signature.getName().equals("getHomeBasics")) {
            return;
        }

        // 打印请求内容
        LinkedHashMap<String, Object> beginLogMap = new LinkedHashMap<>();
        //beginLogMap.put("traceId：", MDC.get(UserConstants.TRACE_ID));
        beginLogMap.put("method：", signature.getName());
        beginLogMap.put("methodType：", request.getMethod());
        beginLogMap.put("className：", signature.getDeclaringTypeName());
        beginLogMap.put("token", SecurityUtils.getToken(request));
//        LoginUser user = SecurityUtils.getLoginUser();
//        if (Objects.nonNull(user)) {
//            beginLogMap.put("user：", SecurityUtils.getUserId() + ":" + SecurityUtils.getUsername());
//        }
        beginLogMap.put("path：", request.getRequestURL().toString());
        beginLogMap.put("ip：", IpUtils.getIpAddr(request));
        // 处理请求参数
        String[] paramNames = ((MethodSignature) signature).getParameterNames();
        Object[] paramValues = joinPoint.getArgs();
        int paramLength = null == paramNames ? 0 : paramNames.length;

        if (paramLength > 0) {
            Map<String, Object> params = new HashMap<>(paramLength);

            for (int i = 0; i < paramLength; i++) {
                params.put(paramNames[i], paramValues[i]);
            }
            beginLogMap.put("parameters", params);
        }
        try {
            log.info(JSONObject.toJSONString(beginLogMap));
        } catch (Exception e) {


        }

    }

    /**
     * 该切面发生异常信息时进行拦截
     *
     * @param joinPoint
     * @param ex
     */
    @AfterThrowing(pointcut = "controllerMethod()", throwing = "ex")
    public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        log.error("连接点方法为：{},参数为：{}, 异常为：{}", methodName, args, ex);
    }
}
